package jmine.tec.utils.annotation.visitor;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Collections;

/**
 * {@link AnnotationVisitor} abstrato para subclasses sobrescreverem os metodos de quaisquer dos visitors
 * 
 * @author takeshi
 * @param <R> R
 */
public abstract class AnnotationVisitorAdapter<R> implements ClassAnnotationVisitor<R>, MethodAnnotationVisitor<R>,
        ParameterAnnotationVisitor<R>, FieldAnnotationVisitor<R> {

    /**
     * {@inheritDoc}
     */
    public Collection<R> onTypeAnnotation(Annotation annotation, Class<?> declared) {
        return Collections.emptyList();
    }

    /**
     * {@inheritDoc}
     */
    public Collection<? extends R> onConstructorAnnotation(Annotation ann, Class<?> declared, Constructor<?> ctor) {
        return this.onMemberAnnotation(ann, declared, ctor);
    }

    /**
     * {@inheritDoc}
     */
    public Collection<? extends R> onMethodAnnotation(Annotation ann, Class<?> declared, Method method) {
        return this.onMemberAnnotation(ann, declared, method);
    }

    /**
     * {@inheritDoc}
     */
    public Collection<? extends R> onConstructorParameterAnnotation(Annotation annotation, Class<?> annotated, Constructor<?> method,
            int parameterIndex, Class<?> parameterType, Type genericType) {
        return onParameterAnnotation(annotation, annotated, parameterIndex, parameterType, genericType, method);
    }

    /**
     * {@inheritDoc}
     */
    public Collection<? extends R> onMethodParameterAnnotation(Annotation annotation, Class<?> annotated, Method method,
            int parameterIndex,
            Class<?> parameterType, Type genericType) {
        return onParameterAnnotation(annotation, annotated, parameterIndex, parameterType, genericType, method);
    }

    /**
     * Chamado para uma anotacao em um parametro de metodo ou construtor
     * 
     * @param annotation annotation
     * @param annotated class
     * @param parameterIndex int
     * @param parameterType type
     * @param genericType type
     * @param annotatedMember member
     * @return {@link Collection} de R
     */
    protected Collection<? extends R> onParameterAnnotation(Annotation annotation, Class<?> annotated, int parameterIndex,
            Class<?> parameterType, Type genericType, Member annotatedMember) {
        return Collections.emptyList();
    }

    /**
     * Chamado para os campos, constutores e metodos
     * 
     * @param annotation {@link Annotation}
     * @param annotated {@link Class}
     * @param annotatedMember {@link Member}
     * @return {@link Collection} de R
     */
    protected Collection<? extends R> onMemberAnnotation(Annotation annotation, Class<?> annotated, Member annotatedMember) {
        return Collections.emptyList();
    }

    /**
     * {@inheritDoc}
     * 
     * @see jmine.tec.utils.annotation.visitor.ClassAnnotationVisitor#acceptsClassAnnotation(java.lang.annotation.Annotation, java.lang.Class)
     */
    public boolean acceptsClassAnnotation(Annotation annotation, Class<?> declaring) {
        return false;
    }

    /**
     * {@inheritDoc}
     * 
     * @see jmine.tec.utils.annotation.visitor.MethodAnnotationVisitor#acceptsConstructor(java.lang.annotation.Annotation,
     * java.lang.reflect.Constructor, java.lang.Class)
     */
    public boolean acceptsConstructor(Annotation ann, Constructor<?> ctor, Class<?> declaring) {
        return false;
    }

    /**
     * {@inheritDoc}
     * 
     * @see jmine.tec.utils.annotation.visitor.ParameterAnnotationVisitor#acceptsConstructorParameter(java.lang.annotation.Annotation,
     * java.lang.Class, java.lang.reflect.Constructor, int, java.lang.Class, java.lang.reflect.Type)
     */
    public boolean acceptsConstructorParameter(Annotation annotation, Class<?> declaring, Constructor<?> ctor, int parameterIndex,
            Class<?> paramterType, Type genericType) {
        return false;
    }

    /**
     * {@inheritDoc}
     * 
     * @see jmine.tec.utils.annotation.visitor.MethodAnnotationVisitor#acceptsMethod(java.lang.annotation.Annotation,
     * java.lang.reflect.Method, java.lang.Class)
     */
    public boolean acceptsMethod(Annotation ann, Method method, Class<?> declaring) {
        return false;
    }

    /**
     * {@inheritDoc}
     * 
     * @see jmine.tec.utils.annotation.visitor.ParameterAnnotationVisitor#acceptsMethodParameter(java.lang.annotation.Annotation,
     * java.lang.Class, java.lang.reflect.Method, int, java.lang.Class, java.lang.reflect.Type)
     */
    public boolean acceptsMethodParameter(Annotation annotation, Class<?> declaring, Method method, int parameterIndex,
            Class<?> paramterType, Type genericType) {
        return false;
    }

    /**
     * {@inheritDoc}
     * 
     * @see jmine.tec.utils.annotation.visitor.FieldAnnotationVisitor#acceptsFieldAnnotation(java.lang.annotation.Annotation,
     * java.lang.Class, java.lang.reflect.Field)
     */
    public boolean acceptsFieldAnnotation(Annotation annotation, Class<?> declaringClass, Field field) {
        return false;
    }

    /**
     * {@inheritDoc}
     * 
     * @see jmine.tec.utils.annotation.visitor.FieldAnnotationVisitor#onFieldAnnotation(java.lang.annotation.Annotation, java.lang.Class,
     * java.lang.reflect.Field)
     */
    public Collection<? extends R> onFieldAnnotation(Annotation annotation, Class<?> declaringClass, Field field) {
        return onMemberAnnotation(annotation, declaringClass, field);
    }

}
